﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Collections.Generic;
using System.Drawing;

namespace Susam
{
    public partial class MainWindow : Form
    {
        enum GridColumn
        {
            ID,
            Checkbox,
            MetadataButton,
            OpenButton,
            Title,
            Authors,
            Publishers,
            Contributors,
            Type,
            Language,
            URI
        }

        private ListBoxManager _lbManager;
        private CheckBox checkboxHeader;

        private delegate void DataGridOperationCallback();
        private delegate void BookCountOperationCallback();

        void Subscribe(BackgorundScanner b)
        {
            b.BackgroundScanStarted += new BackgroundScanStartedHandler(BackgroundScanStarted);
            b.BackgroundScanEnded += new BackgroundScanEndedHandler(BackgroundScanEnded);
        }

        private void BackgroundScanStarted()
        {
            ColorizeBookCountLabel();
        }

        private void BackgroundScanEnded()
        {
            InitializeDisplays();
        }

        private void InitializeDisplays()
        {
            this.ListAllBooks();
            this._lbManager.PopulatePeopleList();
            this.UpdateBookCount();
        }

        private void ColorizeBookCountLabel()
        {
            // This pattern is needed for thread safety.
            if (this.labelBookCount.InvokeRequired)
            {
                BookCountOperationCallback d = new BookCountOperationCallback(ColorizeBookCountLabel);
                this.Invoke(d);
            }
            else
            {
                this.labelBookCount.BackColor = System.Drawing.Color.Green;
                this.labelBookCount.Text = "Indexing is ongoing...";
            }
        }

        private void UpdateBookCount()
        {
            // This pattern is needed for thread safety.
            if (this.labelBookCount.InvokeRequired)
            {
                BookCountOperationCallback d = new BookCountOperationCallback(UpdateBookCount);
                this.Invoke(d);
            }
            else
            {
                this.labelBookCount.BackColor = System.Drawing.Color.Transparent;
                this.labelBookCount.Text = DatabaseManager.Instance.GetBookCount().ToString() + " books indexed.";
            }
        }

        private void ListAllBooks()
        {
            // This pattern is needed for thread safety.
            if (this.dataGridViewBooks.InvokeRequired)
            {
                DataGridOperationCallback d = new DataGridOperationCallback(ListAllBooks);
                this.Invoke(d);
            }
            else
            {
                dataGridViewBooks.Rows.Clear();
                _lbManager.ClearSelected();
                var books = DatabaseManager.Instance.GetFullBookList();
                PopulateBookGrid(books);
                SelectNone();
            }
        }

        public MainWindow()
        {
            InitializeComponent();
            checkboxHeader = new CheckBox();
        }

        private void MainWindow_Load(object sender, EventArgs e)
        {
            _lbManager = new ListBoxManager(this.listBoxMain, this.labelPivot);
            this.Subscribe(BackgorundScanner.Instance);
            InitializeDisplays();
            AddCheckBoxHeader();
        }

        private void AddCheckBoxHeader()
        {
            // This function is adapted from:
            // http://tech.chitgoks.com/2008/11/17/c-add-select-all-deselect-all-checkbox-in-column-header-in-datagridview-control/

            // add checkbox header
            Rectangle rect = dataGridViewBooks.GetCellDisplayRectangle(1, -1, true);
            // set checkbox header to center of header cell
            rect.X = rect.Location.X + 3;
            rect.Y = rect.Location.Y + 3;

            checkboxHeader.Name = "checkboxHeader";
            checkboxHeader.Size = new Size(18, 18);
            checkboxHeader.BackColor = Color.Transparent;
            checkboxHeader.Location = rect.Location;
            checkboxHeader.CheckedChanged += new EventHandler(checkboxHeader_CheckedChanged);

            dataGridViewBooks.Controls.Add(checkboxHeader);
            SelectNone();
        }

        private void checkboxHeader_CheckedChanged(object sender, EventArgs e)
        {
            for (int i = 0; i < dataGridViewBooks.RowCount; i++)
            {
                dataGridViewBooks[(int)GridColumn.Checkbox, i].Value = checkboxHeader.Checked;
            }
        }

        private void SelectNone()
        {
            checkboxHeader.Checked = false;
        }

        private void PopulateBookGrid(IEnumerable<BookDisplay> books)
        {
            foreach (var book in books)
            {
                DataGridViewRow row = new DataGridViewRow();
                row.CreateCells(dataGridViewBooks);

                row.Cells[(int)GridColumn.ID].Value = book.ID;
                row.Cells[(int)GridColumn.Checkbox].Value = false;
                row.Cells[(int)GridColumn.MetadataButton].ToolTipText = "View full metadata";
                row.Cells[(int)GridColumn.OpenButton].ToolTipText = "Open with the default viewer";
                row.Cells[(int)GridColumn.Title].Value = book.Title;
                row.Cells[(int)GridColumn.Authors].Value = book.Authors;
                row.Cells[(int)GridColumn.Publishers].Value = book.Publishers;
                row.Cells[(int)GridColumn.Contributors].Value = book.Contributors;
                row.Cells[(int)GridColumn.Type].Value = book.Type;
                row.Cells[(int)GridColumn.Language].Value = book.Language;
                row.Cells[(int)GridColumn.URI].Value = book.URI;
                dataGridViewBooks.Rows.Add(row);
            }
        }

        private void buttonPeople_Click(object sender, EventArgs e)
        {
            _lbManager.PopulatePeopleList();
        }

        private void buttonLanguage_Click(object sender, EventArgs e)
        {
            _lbManager.PopulateLanguageList();
        }

        private void buttonFileType_Click(object sender, EventArgs e)
        {
            _lbManager.PopulateFileTypeList();
        }

        private void buttonAllBooks_Click(object sender, EventArgs e)
        {
            ListAllBooks();
        }

        private void buttonAbout_Click(object sender, EventArgs e)
        {
            AboutBox about = new AboutBox();
            about.ShowDialog();
        }

        private void buttonConfiguration_Click(object sender, EventArgs e)
        {
            Configuration conf = new Configuration();
            conf.ShowDialog();
        }

        private void listBoxMain_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (null == listBoxMain.SelectedItem)
            {
                return;
            }

            IBooksOfEntity entity = (IBooksOfEntity)listBoxMain.Tag;
            Pair selected = (Pair)listBoxMain.SelectedItem;
            var books = entity.GetBooksViaID(selected.ID);

            dataGridViewBooks.Rows.Clear();
            PopulateBookGrid(books);
            SelectNone();
        }

        private void dataGridViewBooks_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == dataGridViewBooks.Columns[(int)GridColumn.Checkbox].Index && e.RowIndex >= 0)
            {
                Console.WriteLine("Checkbox on row {0} clicked", e.RowIndex);
                dataGridViewBooks[(int)GridColumn.Checkbox, e.RowIndex].Value = !(bool)(dataGridViewBooks[(int)GridColumn.Checkbox, e.RowIndex].Value);
            }
            else if (e.ColumnIndex == dataGridViewBooks.Columns[(int)GridColumn.MetadataButton].Index && e.RowIndex >= 0)
            {
                Console.WriteLine("Button on row {0} clicked", e.RowIndex);
                Console.WriteLine("Opening metadata for: {0}", dataGridViewBooks.Rows[e.RowIndex].Cells[(int)GridColumn.URI].Value);

                PublicationMetadata pm = new PublicationMetadata((String)dataGridViewBooks.Rows[e.RowIndex].Cells[(int)GridColumn.URI].Value);
                pm.ShowDialog();
            }
            else if (e.ColumnIndex == dataGridViewBooks.Columns[(int)GridColumn.OpenButton].Index && e.RowIndex >= 0)
            {
                Console.WriteLine("Button on row {0} clicked", e.RowIndex);
                Console.WriteLine("Opening file: {0}", dataGridViewBooks.Rows[e.RowIndex].Cells[(int)GridColumn.URI].Value);

                System.Diagnostics.Process.Start(dataGridViewBooks.Rows[e.RowIndex].Cells[(int)GridColumn.URI].Value.ToString());
            }
        }
    }
}
